prepare.js ➔ addAbeAttrForBlock   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
nc 2
nop 3
dl 0
loc 20
rs 9.4285
1
import Handlebars from 'handlebars'
2
import striptags from 'striptags'
3
4
import {
5
  cmsData
6
  ,config
7
  ,cmsTemplates
8
} from '../../'
9
10
export function addAbeAttrSingleTab(key, elem, htmlAttribute = null) {
11
  var res = ''
12
13
  var valueOfAttritube = key.replace(/\./g, '-')
14
  key = cmsData.regex.validDataAbe(valueOfAttritube)
15
  
16
  if (htmlAttribute != null) {
17
    res = ' data-abe-attr-' + valueOfAttritube + '="'  + htmlAttribute + '"' + ' data-abe-' + valueOfAttritube + '="'  + key + '"' + elem
18
  }else {
19
    res = ' data-abe-' + key + '="'  + key + '" ' + elem
20
  }
21
22
  return res
23
}
24
25
export function addAbeAttrForBlock(key, elem, htmlAttribute = null) {
26
  var res = ''
27
28
  var valueOfAttritube = key.split('.')
29
  var parentKey = valueOfAttritube.shift()
30
  valueOfAttritube = `${parentKey}[index].${valueOfAttritube[0].replace(/\./g, '-')}`
31
  var valueOfAttritubeIndexed = valueOfAttritube.replace(/\[index\]/, '{{@index}}')
32
  key = cmsData.regex.validDataAbe(valueOfAttritube)
33
34
  if (htmlAttribute) {
35
36
    res = ` data-abe-attr-${valueOfAttritube}="${htmlAttribute}"  data-abe-${valueOfAttritube}="${key}"`
37
      + ` data-abe-attr-${valueOfAttritubeIndexed}="${htmlAttribute}" data-abe-${valueOfAttritubeIndexed}="${key}"${elem}`
38
  }else {
39
    res = ` data-abe-${valueOfAttritube}="${key}"`
40
      + ` data-abe-${valueOfAttritubeIndexed}="${key}" ${elem}`
41
  }
42
43
  return res
44
}
45
46
/**
47
 * THIS:
48
<span>{{abe type='text' key='text_visible'}}</span>
49
50
 * BECOME:
51
<span data-abe-text_visible="text_visible" >{{abe type='text' key='text_visible'}}</span>
52
53
 * @param {[type]} template [description]
54
 */
55
export function addAbeDataAttrForHtmlTag(template) {
56
  var match
57
  var key
58
  var getattr
59
  var newTemplate = template
60
61
  while (match = cmsData.regex.abePattern.exec(template)) {
62
    key = cmsData.regex.getAttr(match, 'key')
63
64
    if (!cmsData.regex.isSingleAbe(match, newTemplate)) {
65
      key = key.replace('.', '{{@index}}.')
66
    }
67
68
    getattr = key.replace(/\./g, '-')
69
70
    newTemplate = newTemplate.replace(
71
      cmsData.regex.escapeTextToRegex(match[0], 'g'),
72
      ' data-abe-' + cmsData.regex.validDataAbe(getattr) + '="'  + getattr + '" ' + match[0]
73
    )
74
  }
75
76
  return newTemplate
77
}
78
79
export function addHasAbeAttr(text) {
80
  return text.replace('}}', ' has-abe=1}}')
81
}
82
83
export function getAbeAttributeData(match, text, htmlAttribute, abeTag) {
84
  var valueOfAttritube
0 ignored issues
show
Unused Code introduced by
The variable valueOfAttritube seems to be never used. Consider removing it.
Loading history...
85
  var key = cmsData.regex.getAttr(match, 'key')
86
  var res
87
88
  if (cmsData.regex.isSingleAbe(match, text)) {
89
    res = addAbeAttrSingleTab(key, abeTag, htmlAttribute)
90
  } else {
91
    res = addAbeAttrForBlock(key, abeTag, htmlAttribute)
92
  }
93
94
  return res
95
}
96
97
/**
98
 *
99
 * IF ABE TAG SINGLE (NOT ABE EACH STATEMENT)
100
 * 
101
 * THIS:
102
<img src="{{abe type='image' key='image_key' tab='default'}}" alt="">
103
104
 * BECOME:
105
<img data-abe-attr-image_key="src" data-abe-image_key="image_key" data-abe-attr-image_key="src"
106
data-abe-image_key="image_key" src="{{abe type='image' key='image_key' tab='default' has-abe=1 has-abe=1}}" alt="">
107
108
 *
109
 * IF ABE EACH TAG
110
 * THIS:
111
{{#each test}}
112
  <img src="{{abe type='image' key='test.img' desc='test_img' tab='default'}}" alt="">
113
{{/each}}
114
115
 * BECOME:
116
{{#each test}}
117
  <img data-abe-attr-test[index].img="src" data-abe-test[index].img="test[index].img" src="{{abe type='image' key='test.img' desc='test_img' tab='default' has-abe=1}}" alt="">
118
{{/each}}
119
120
 * @param {[type]} template [description]
121
 */
122
export function addAbeDataAttrForHtmlAttributes(template) {
123
  var text = template.replace(/<([A-Za-z]+)/g, '\nABE_SPLIT<$1')
124
  let abeTagIntoAttribute = text.match(cmsData.regex.abeAsAttributePattern)
125
126
  if (abeTagIntoAttribute != null) {
127
    Array.prototype.forEach.call(abeTagIntoAttribute, (abeIntoTag) => {
128
      let matchAbeTag = /({{abe.*?[\s\S].*?}})/g.exec(abeIntoTag)
129
130
      if(matchAbeTag != null && matchAbeTag[1] != null) {
131
        var toReplace = cmsTemplates.prepare.getAbeAttributeData(matchAbeTag[1], text, (abeIntoTag.split('=')[0]).trim(), abeIntoTag)
132
133
        toReplace = toReplace.replace(
134
          cmsData.regex.escapeTextToRegex(matchAbeTag[1]),
135
          cmsTemplates.prepare.addHasAbeAttr(matchAbeTag[1])
136
        )
137
138
        text = text.replace(
139
          cmsData.regex.escapeTextToRegex(abeIntoTag),
140
          toReplace
141
        )
142
      }
143
    })
144
  }
145
  text = text.replace(/\nABE_SPLIT</g, '<')
146
147
  return text
148
}
149
150
/**
151
 * Example:
152
 *
153
 *
154
 * THIS:
155
{{abe type='data' key='data_key' source='select title from article' display='title' editable='true' tab='default'}}
156
157
{{#each data_key}}
158
  {{title}}
159
{{/each}}
160
161
 *
162
 * BECOME THIS
163
164
{{abe type='data' key='data_key' source='select title from article' display='title' editable='true' tab='default'}}
165
166
{{#each data_key}}
167
  {{title}}
168
{{/each}}<!-- [[data_key]] %7B%7B%23each%20data_key%7D%7D%0A%09%7B%7Btitle%7D%7D%0A%7B%7B/each%7D%7D -->
169
170
 * @param {[type]} template [description]
171
 * @param {[type]} json     [description]
172
 */
173
export function addAbeSourceComment(template, json) {
174
175
  if(typeof json.abe_source !== 'undefined' && json.abe_source !== null) {
176
    var keys = Object.keys(json.abe_source)
177
    
178
    for(var i in keys) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
179
      var replaceEach = new RegExp(`<!-- \\[\\[${keys[i]}\\]\\][\\s\\S]*?-->`, 'g')
180
      var regexEachKey = new RegExp(`{{#each ${keys[i]}}}`, 'g')
0 ignored issues
show
Unused Code introduced by
The variable regexEachKey seems to be never used. Consider removing it.
Loading history...
181
      template = template.replace(replaceEach, '')
182
183
      var patAttrSource = new RegExp(' ([A-Za-z0-9\-\_]+)=["|\'].*?({{' + keys[i] + '}}).*?["|\']', 'g')
184
      var patAttrSourceMatch = template.match(patAttrSource)
185
186
      if(patAttrSourceMatch != null) {
187
        let checkEscapedRegex = /["|'](.*?)["|']/
188
        let patAttrSourceInside = new RegExp('(\\S+)=["\']?((?:.(?!["\']?\\s+(?:\\S+)=|[>"\']))+.)["\']?({{' + keys[i] + '}}).*?["|\']', 'g')
189
        Array.prototype.forEach.call(patAttrSourceMatch, (pat) => {
190
          let patAttrSourceCheck = patAttrSourceInside.exec(pat)
191
          if(patAttrSourceCheck != null) {
192
            
193
            let checkEscaped = checkEscapedRegex.exec(patAttrSourceCheck[0])
194
            if(checkEscaped != null && checkEscaped.length > 0) {
195
              checkEscaped = escape(checkEscaped[1])
196
              template = template.replace(
0 ignored issues
show
Bug introduced by
The variable template is changed as part of the for-each loop for example by template.replace(replaceEach, "") on line 181. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
197
                patAttrSourceCheck[0],
198
                ` data-abe-attr="${patAttrSourceCheck[1]}" data-abe-attr-escaped="${checkEscaped}" data-abe="${keys[i]}" ${patAttrSourceCheck[0]}`
0 ignored issues
show
introduced by
The variable i is changed by the for-each loop on line 178. Only the value of the last iteration will be visible in this function if it is called outside of the loop.
Loading history...
199
              )
200
            }
201
          }
202
        })
203
      }
204
205
      var eachSource = new RegExp(`({{#each ${keys[i]}}[\\s\\S a-z]*?{{\/each}})`, 'g')
206
      var matches = template.match(eachSource)
207
      if(typeof matches !== 'undefined' && matches !== null) {
208
        Array.prototype.forEach.call(matches, (match) => {
209
          template = template.replace(match, `${match}<!-- [[${keys[i]}]] ${cmsTemplates.encodeAbeTagAsComment(match)} -->`)
0 ignored issues
show
Bug introduced by
The variable template is changed as part of the for-each loop for example by template.replace(replaceEach, "") on line 181. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
introduced by
The variable i is changed by the for-each loop on line 178. Only the value of the last iteration will be visible in this function if it is called outside of the loop.
Loading history...
210
        })
211
      }
212
    }
213
  }
214
215
  return template
216
}
217
218
/**
219
 * THIS:
220
<span>{{abe type='text' key='text_visible'}}</span>
221
222
 * BECOME:
223
<span><abe>{{abe type='text' key='text_visible'}}</abe></span>
224
225
 * @param {[type]} template [description]
226
 */
227
export function addAbeHtmlTagBetweenAbeTags(template) {
228
  var match
229
  var templateNoDom = striptags(template)
230
  
231
  // {{#each tags may be declared outside of an html Tag}}
232
  while (match = cmsData.regex.eachBlockPattern.exec(template)) {
233
    template = template.replace(cmsData.regex.escapeTextToRegex(match[1], 'g'), '<abe>' + match[1].trim() + '</abe>')
234
  }
235
  
236
  while (match = cmsData.regex.abeAsTagPattern.exec(templateNoDom)) {
237
    template = template.replace(cmsData.regex.escapeTextToRegex(match[1], 'g'), '<abe>' + match[1].trim() + '</abe>')
238
  }
239
240
  return template
241
}
242
243
/**
244
 * THIS:
245
[index].
246
247
 * BECOME:
248
{{@index}}-
249
250
 *  @param  {[type]} template [description]
251
 * @return {[type]}          [description]
252
 */
253
export function replaceAbeEachIndex(template) {
254
  return template.replace(/\[index\]\./g, '{{@index}}-')
255
}
256
257
export function removeHiddenAbeTag(template) {
258
  return template.replace(/(\{\{abe.*visible=[\'|\"]false.*\}\})/g, '')
259
}
260
261
/**
262
 * Remove {{abe type=*}} from html if attribute visible="false"
263
 * @param  {[type]} template [description]
264
 * @return {[type]}          [description]
265
 */
266
export function removeHandlebarsRawFromHtml(template) {
267
  return template.replace(/\{\{\{\{\/?raw\}\}\}\}/g, '')
268
}
269
270
/**
271
 * split {{#each}}...{{/each}} into an array
272
 * 
273
 * @param  {[type]} template [description]
274
 * @return {[type]}          [description]
275
 */
276
export function splitEachBlocks(template) {
277
  var block
278
  var blocks = []
279
280
  while (block = cmsData.regex.blockPattern.exec(template)) {
281
    blocks.push(block[1])
282
  }
283
284
  return blocks
285
}
286
287
export function indexEachBlocks(template, json, onlyHtml) {
288
  // create an array of {{each}} blocks
289
  var blocks = cmsTemplates.prepare.splitEachBlocks(template)
290
291
  Array.prototype.forEach.call(blocks, (block) => {
292
    var key = block.match(/#each (.*)\}\}/)[1]
293
    var match
294
295
    if(!onlyHtml) {
296
297
      var voidData = {}
298
      voidData[key] = [{}]
299
      var blockCompiled = Handlebars.compile(block.replace(/{{abe (.*?["'])[ ]?( has\-abe=1)?}}/g, '[[abe $1]]').replace(new RegExp(`\\.\\.\/${config.meta.name}`, 'g'), config.meta.name))
300
      var blockHtml = blockCompiled(voidData, {data: {intl: config.intlData}}).replace(/\[\[abe (.*?)\]\]/g, '{{abe $1}}')
301
302
      // je rajoute un data-abe-block avec index sur tous les tags html du bloc each
303
      var textEachWithIndex = block.replace(/(<(?![\/])[A-Za-z0-9!-]*)/g, '$1 data-abe-block="' + key + '{{@index}}"')
304
305
      // I add an each block commentary only if the each block key != key of a type=data abe tag
306
      var keys = []
307
      if(typeof json.abe_source !== 'undefined' && json.abe_source !== null) {
308
        keys = Object.keys(json.abe_source)
309
      }
310
      if(keys.indexOf(key) === -1){
311
        template = template.replace(block, textEachWithIndex + `<!-- [[${key}]] ${cmsTemplates.encodeAbeTagAsComment(blockHtml)} -->`)
312
      }
313
    }
314
315
    // Pour chaque tag Abe
316
    while (match = cmsData.regex.abeTag.exec(block)) {
317
      template = cmsTemplates.prepare.addAbeDictionnary(template, match[0], key)
0 ignored issues
show
Bug introduced by
The variable template is changed as part of the while loop for example by cmsTemplates.prepare.add...template, match.0, key) on line 317. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
318
    } 
319
  })
320
321
  return template
322
}
323
324
/**
325
 * split {{#each}}...{{/each}} into an array
326
 *
327
 * THIS:
328
  {{abe type='text' key='test.title' desc='test title' tab='default'}}
329
330
 * BECOME THIS:
331
  {{abe dictionnary='test' type='text' key='test.title' desc='test title' tab='default'}}
332
333
 * 
334
 * @param  {[type]} template [description]
335
 * @return {[type]}          [description]
336
 */
337
export function addAbeDictionnary(template, match, key) {
338
  if(cmsData.regex.isEachStatement(match)) return
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
339
340
  if(cmsData.regex.isBlockAbe(match)){
341
    var abeDictionnary = match.replace(new RegExp('(key=[\'|"])' + key + '.', 'g'), '$1' + key + '[index].')
342
                               .replace(/\{\{abe/, '{{abe dictionnary=\'' + key + '\'')
343
344
    template = template.replace(match, abeDictionnary)
345
  }
346
347
  return template
348
}
349